1. Technical Field
The present disclosure relates generally to information processing systems and, more specifically, to resource-aware scheduling of instructions.
2. Background Art
A compiler is a software program that translates a source program (referred to herein as “source code”) into machine instructions (referred to herein as “object code”) that can be executed on a hardware processor. The source code is typically written in a high-level programming language such as C, C++, Microengine C, Pascal, FORTRAN, or the like.
When generating object code, a compiler operates on the entire source program as a whole. This is in contrast to, for example, interpreters that analyze and execute each line of source code in succession. Because compilers operate on the entire source program, they may perform optimizations that attempt to make the resultant object code more efficient. Optimizing compilers attempt to make the object code more efficient in terms of execution time and/or memory usage. Examples of optimizing compilers include the Intel® C Compiler, Intel® C++ Compiler, and the Intel® Fortran Compiler.
An optimizing compiler may generate an intermediate representation of the source code. For a single compiler engine that is designed for more than one source code language (such as, for instance, a single compiler engine for C, C++, and FORTRAN90), the compiler may generate a common intermediate representation, so that many of the optimization techniques are applicable irrespective of the source language.
A compiler typically includes a back end code generator that schedules instructions and generates the ultimate object code. The task of the code generator is to translate the optimized intermediate representation into machine code for the desired target processor. Because compilers translate source code into object code that is unique for each type of processor, many compilers are available for the same language. For those compilers whose target processor is an Intel® Itanium® processor, for example, the compiler is responsible for efficiently exploiting the available instruction-level parallelism of such processors, and for keeping the execution units of such processors as fully utilized as possible during each processing cycle.
Typically, scheduling of instructions is handled by the code generator according to a heuristic-based approach such as a list scheduling algorithm. In such approach, scheduling priorities for instructions are calculated based on their dependence height in a directed acyclic graph (DAG) that represents the scheduling region under consideration. Such a scheduling approach may fail to provide an optimal schedule for regions that are resource-bound rather than dependence-bound. The compiler and methods described herein address these and other issues associated with scheduling of instructions by a compiler.